package bancosys.tec.services.implementor.descriptor;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import jmine.tec.di.cache.TypeMatchLookup;
import jmine.tec.di.type.BigDecimalTypeConverter;
import jmine.tec.di.type.DoubleTypeConverter;
import jmine.tec.di.type.IntegerTypeConverter;
import jmine.tec.di.type.JavaEnumTypeConverter;
import jmine.tec.di.type.LongTypeConverter;
import jmine.tec.di.type.TypeConverter;
import jmine.tec.di.type.TypeConvertionException;
import jmine.tec.di.type.URLTypeConverter;
import bancosys.tec.persist.base.enumx.EnumUtils;
import bancosys.tec.persist.base.enumx.IntValuedEnum;
import bancosys.tec.persist.base.enumx.StringValuedEnum;
import bancosys.tec.utils.date.Date;
import bancosys.tec.utils.date.DateUtils;
import bancosys.tec.utils.date.Timestamp;

/**
 * @author takeshi.fukushima
 */
public final class ServiceTypeConverters {

    /**
     */
    private ServiceTypeConverters() {
        // empty
    }

    /**
     * Transforma um array em uma lista
     * 
     * @param classes as classes
     * @return {@link Collection}
     */
    @SuppressWarnings("unused")
    private static Collection<Class<?>> toCollection(Class<?>... classes) {
        List<Class<?>> list = new ArrayList<Class<?>>(classes.length);
        for (Class<?> class1 : classes) {
            list.add(class1);
        }
        return list;
    }

    /**
     * Devolve um {@link TypeMatchLookup} para ser usado em servicos
     * 
     * @return {@link TypeMatchLookup}
     */
    public static TypeMatchLookup<TypeConverter<?>> initServiceTypeConvertion() {
        TypeMatchLookup<TypeConverter<?>> t = new TypeMatchLookup<TypeConverter<?>>();
        t.registerNew(new TypeConverter<Date>() {
            public Date convert(String value, Class<?> desiredType) throws TypeConvertionException {
                return DateUtils.getNonLenientDateByViewDateDDMMYY(value);
            }

            public boolean isTypeCompatible(Class<?> type) {
                return Date.class == type;
            }
        });

        t.registerNew(new IntegerTypeConverter());

        t.registerNew(new LongTypeConverter());

        t.registerNew(new DoubleTypeConverter());
        t.registerNew(new JavaEnumTypeConverter());
        t.registerNew(new BigDecimalTypeConverter());
        t.registerNew(new URLTypeConverter());

        t.registerNew(new TypeConverter<Boolean>() {

            public Boolean convert(String value, Class<?> desiredType) throws TypeConvertionException {
                if (value.equalsIgnoreCase("SIM") || value.equalsIgnoreCase("TRUE")) {
                    return true;
                } else if (value.equalsIgnoreCase("NÃO") || value.equalsIgnoreCase("FALSE")) {
                    return false;
                }
                throw new IllegalArgumentException();
            }

            public boolean isTypeCompatible(Class<?> type) {
                return type == Boolean.class || type == boolean.class;
            }
        });

        t.registerNew(new TypeConverter<StringValuedEnum>() {

            @SuppressWarnings("unchecked")
            public StringValuedEnum convert(String value, Class desiredType) throws TypeConvertionException {
                return (StringValuedEnum) EnumUtils.getApacheEnumByValue(desiredType, value);
            }

            public boolean isTypeCompatible(Class<?> declaredRawType) {
                return StringValuedEnum.class.isAssignableFrom(declaredRawType);
            }

        });

        t.registerNew(new TypeConverter<IntValuedEnum>() {

            @SuppressWarnings("unchecked")
            public IntValuedEnum convert(String value, Class desiredType) throws TypeConvertionException {
                return (IntValuedEnum) EnumUtils.getApacheEnumByValue(desiredType, value);
            }

            public boolean isTypeCompatible(Class<?> declaredRawType) {
                return IntValuedEnum.class.isAssignableFrom(declaredRawType);
            }
        });

        t.registerNew(new TypeConverter<Timestamp>() {
            public Timestamp convert(String value, Class<?> desiredType) throws TypeConvertionException {
                if (value == null) {
                    return null;
                }
                try {
                    return DateUtils.parseTimestamp(value);
                } catch (ParseException e) {
                    throw new TypeConvertionException(e, desiredType, value);
                }
            }

            public boolean isTypeCompatible(Class<?> type) {
                return Timestamp.class == type;
            }
        });

        return t;
    }
}
